/**
 * 
 */
package langnstats.project.languagemodel.srilm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import langnstats.project.languagemodel.srilm.SriLMParameters.DiscountingMethod;
import langnstats.project.lib.ExternalLanguageModel;
import langnstats.project.lib.WordType;

/**
 * @author qing
 *
 */
public class SriLM extends ExternalLanguageModel {
	private String tmpResultFile ="";
	private BufferedReader rd = null;
	private boolean lineStart = true;
	/**
	 * 
	 */
	private static final long serialVersionUID = 5249442568678383435L;

	public SriLM(String corpus,  int order,int[] cutoff, int[] maxdisc,DiscountingMethod disc) throws IOException, InterruptedException {
		super((new SriLMParameters(disc,
				order,corpus+".lm",corpus,cutoff,maxdisc)).toString(), corpus);
	}

	/**
	 * 
	 */


	/* (non-Javadoc)
	 * @see langnstats.project.lib.ExternalLanguageModel#convertNextWord(java.lang.String, java.io.PrintWriter)
	 */
	@Override
	public void convertNextWord(String str, PrintWriter wr) {
		if(lineStart){
			wr.print("<s> ");
			lineStart = false;
		}
		wr.print(str);
		wr.print(" ");
		if(str.equals("<PERIOD>")){
			wr.println("</s>");
			lineStart = true;
		}
	}

	/* (non-Javadoc)
	 * @see langnstats.project.lib.ExternalLanguageModel#parseNextWord()
	 */
	@Override
	public Map<String, Double> parseNextWord() {
		// We assume that the <s> </s> already filtered
		String line = null;
		try {
			if(rd==null|| null == (line = rd.readLine())){
				System.err.println("Failed in reading new result!");
				return null;
			}
		} catch (IOException e) {
			System.err.println("Failed in reading new result!");
			e.printStackTrace();
		}
		Map<String,Double> dbl = new TreeMap<String,Double>();
		String[] values = line.split("|");
		for(int i = 0 ;i < values.length ; i++){
			if(values[i].length()==0){
				continue;
			}
			String[] pair = values[i].split(",");
			if(pair.length == 2){
				dbl.put(pair[0],Double.parseDouble(pair[1]));
			}
		}
		return dbl;
	}

	/* (non-Javadoc)
	 * @see langnstats.project.lib.ExternalLanguageModel#prepare(langnstats.project.lib.WordType[])
	 */
	@Override
	public void prepare(WordType[] allWordType) {
		PrintWriter wr = null;
		try {
			wr = new PrintWriter(new FileWriter(getTempFile()));
		} catch (IOException e) {
			System.err.println("Error, training failed due to IO Exception on Temp File: " + getTempFile());
			e.printStackTrace();
			return ;
		}
		WordType[] wt = allWordType;
		for(int i = 0 ; i<wt.length ; i++){
			String str = wt[i].getOriginalTag();
			convertNextWord(str,wr);
		}
		wr.close();
		Runtime runtime = Runtime.getRuntime();
		String actualCommand = "";
		tmpResultFile = tmpResultFile+".res";
		try {
			actualCommand = getCommandLine() + " decode " + getTempFile() + " " + getLmFile() +" " + tmpResultFile; 
 			Process process = runtime.exec(actualCommand);
			process.waitFor();
		} catch (IOException e) {
			System.err.println("Training Failed! The command line: " + actualCommand);
			e.printStackTrace();
		} catch (InterruptedException e) {
			System.err.println("Training program terminated! The command line: " + actualCommand);
			e.printStackTrace();
		}
		File f = new File(tmpResultFile);
		if(f.exists()){
			System.err.println("Training OK, outputed LM: " + tmpResultFile);
		}else{
			System.err.println("Training Failed, expected LM file: " + tmpResultFile + " does not exist");
			tmpResultFile=null;
			return;
		}
		try {
			rd = new BufferedReader(new FileReader(tmpResultFile));
		} catch (FileNotFoundException e) {
			System.err.println("Open result file failed !" + tmpResultFile);
			e.printStackTrace();
		}
	}

}
